home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- * ispCODE5B.c *
- * ispCODE for ispLSI Devices Using the Industry Standard ISP State Machine. *
- * Lattice Semiconductor Corp. Copyright 1996. *
- * *
- * ISP(tm) daisy chain turbo programming is supported by ispCODE. *
- * *
- * The function of this ispCODE is to utilize the Industry Standard ISP state*
- * machine in the ispLSI devices for programming and verification. The input *
- * file for ispCODE is SLIM ispSTREAM files or Super SLIM ispSTREAM files. *
- * *
- * The file size of SLIM ispSTREAM is at least 50% less than the FULL *
- * ispSTREAM. The saving comes from stripping out the instructions and field *
- * size identifiers. The code size of ispCODE V5.00 for processing the SLIM *
- * ispSTREAM is also reduced by 50% as a result. *
- * *
- * The file size of Super SLIM ispSTREAM is about 50% less than the SLIM *
- * ispSTREAM. The extra saving comes from replacing long chain of 0xFFs with *
- * the number of consecutive 0xFF bytes. For example: *
- * 0xFF,0xFF,0xFF,0xC3 is reduced to 0xFF,0x02,0xC3 *
- * *
- * The only restriction on the SLIM ispSTREAM is that the daisy chain must be*
- * of the same ISP device types. For example: *
- * A chain of ispGAL22v10 devices. *
- * A chain of ispLSI 1032 devices. *
- * A chain of ispLSI 2032 devices. *
- * *
- * *
- * The SLIM ispSTREAM file is created by the command line program dld2isp.exe*
- * v4.02 with the option s selected. For example: type *
- * dld2isp design.dld s *
- * The Super SLIM ispSTREAM file is created by the command line program *
- * dld2isp.exe v4.03 with the option ss selected. For example: type *
- * dld2isp design.dld ss *
- * *
- * The program isp2hex.exe and the source code isp2hex.c can be used to *
- * convert the ispSTREAM file from binary format to C code for linking with *
- * ispcode5.c. *
- * *
- * All ispLSI devices support the Lattice Semiconductor pioneered UES *
- * feature. If the UES is appended into the JEDEC files using the UES editor *
- * on ISP Daisy Chain Download program, the resultant ispSTREAM will take *
- * care of programming and verifying the UES data. *
- * *
- * Note: The UES length of most ispLSI devices is the same as their data *
- * length. If it is found on the data book that they are not the same *
- * such as ispLSI 3256 and 6192 devices, only the last 160 bits are *
- * referred to as UES. For example: The data length of ispLSI 3256 *
- * devices is 338 bits and the UES length is 160 bits as shown in the *
- * data book. Pulse SCLK 338-160=178 times to flush out the phantum *
- * bits first then read the 1st UES bit. *
- * *
- * Revision history: *
- * 5B.000 Howard Tang 06/28/96 Convert from V4.0 to support ISP(tm) *
- * programming using the industry standard ISP*
- * state machine with the SLIM ispSTREAM. *
- * 5B.001 Howard Tang 10/16/96 Add support to Super SLIM ispSTREAM. *
- * 5B.002 Howard Tang 10/21/96 Update the code to support isp2hex.exe *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <dos.h>
- #include <stdlib.h>
- #include <string.h>
- #include "lattice.h"
- #include "istream.hex"
-
- /*Global variables */
- static unsigned char curch; /*5B.002 the current data from ispSTREAM*/
- unsigned char *fp; /*5B.002 pointer to the ispSTREAM*/
- static short int bit=0; /*the current bit read from ispSTREAM*/
-
- static short int inputport=inport1, /*port address for the input port*/
- outputport=outport1; /*port address for the output port*/
- static short int isp_pins=NUL; /*3.02 holds the value of parallel port*/
- /* intialized to drive all pins to LOW*/
- /*prototypes*/
- void pulse_width(unsigned short int milliseconds);
- void execute(void);
- void move_to_id_state(void);
- short int ispstream_pump(short int operation, short int *end);
- void error_handler(short int rcode, char *message);
- unsigned char GetByte(void);
- void ReadispSTREAMHeader(short int *ChainLength, short int *ErasePulse,
- short int *ProgramPulse, short int *RowLength,
- unsigned short int *DataSize,
- unsigned short int *IDStreamLength);
- char ispRead(unsigned short int DataSize, unsigned char *OutData);
- void ReadispSTREAMData(unsigned short int DataSize, unsigned char *InData,
- char SS);
- void ispInstruction(short int ChipCount, unsigned char Command);
- void ispAddress(short int ChipCount, short int RowLength);
- void ispData( unsigned char *InData, unsigned short int DataSize);
-
- /***************************************************************************
- Function: isp_setpin(byte pins, byte value)
-
- Purpose:
- To apply the specified value to the pins indicated. This routine will
- likely be modified for specific systems. As an example, this code
- is for the PC, as described below.
-
- This routine uses the IBM-PC standard Parallel port, along with the
- schematic shown in Lattice documentation, to apply the signals to the
- programming loop.
-
- PC Parallel port pin Signal name
- -------------------- -----------
- 2 out_SDI
- 3 out_SCLK
- 4 out_MODE
- 5 out_ISP
- 6 out_RESET
- 7 DO5
- 8 out_SENSE_CABLE_OUT
- 9 DO7
- 10 in_SDO
- 12 in_CABLE_SENSE_IN
- 15 in_VCC_OK
- 20 GND
-
- Parameters:
- - pins, which is actually a set of bit flags (defined in lattice.h)
- that correspond to the bits of the data port. Each of the I/O port
- bits that drives an isp programming pin is assigned a flag
- (through a #define) corresponding to the signal it drives. To
- change the value of more than one pin at once, the flags are added
- together, much like file access flags are.
-
- The bit flags are only set if the pin is to be changed. Bits that
- do not have their flags set do not have their levels changed. The
- state of the port is always manintained in the static global
- variable isp_pins, so that each pin can be addressed individually
- without disturbing the others.
-
- - value, which is either HIGH (0x01 ) or LOW (0x00 ). Only these two
- values are valid. Any non-zero number sets the pin(s) high.
-
- Returns: nothing.
-
-
- **************************************************************************/
- void isp_setpin(unsigned char pins, unsigned char value)
- {
- /* isp_pins is a Global value that keeps track of the current state
- of the pins */
-
- if( value ) /* set flagged pins HIGH */
- isp_pins = pins | isp_pins;
- else /* set flagged pins LOW */
- isp_pins = ~pins & isp_pins;
-
- /* value is put on Parallel port pins */
- outp(outputport, isp_pins);
-
- } /* isp_setpin() */
-
-
- /***************************************************************************
- Function: isp_SDO()
-
- Purpose:
- To get the value of the SDO pin from the input port.
-
- This routine is specific to the PC parallel port setup, but can easily
- be changed to address each user's hardware.
-
- Parameters: none
-
- Returns: The value of SDO, as a byte, with a value of either 0 or 1.
-
- Notes:
- - This routine uses the I/O port addresses contained in the global
- variable inputport, declared in the lattice.h file. If that
- variable is not set, these routines will not work.
-
-
- ****************************************************************************/
- unsigned char isp_SDO(void)
- {
- /* MUST return either 0x00 or 0x01 */
- return( (unsigned char) ((inp(inputport) & in_SDO ) ? HIGH : LOW) );
-
- } /* isp_SDO() */
-
- /*************************************************************
- * *
- * PULSE_WIDTH *
- * This procedure produce accurate timing only on straight PC *
- * DOS. The timing is not guarantee if use on Windows DOS. *
- * The delay() function is available only from BORLAND. *
- * *
- * Users must devise their own timing procedures to ensure *
- * the specified minimum delay is observed when using *
- * different platform. *
- *************************************************************/
-
-
- void pulse_width(unsigned short int milliseconds)
- {
- delay(milliseconds);
- }
-
-
-
- /*************************************************************
- * *
- * GETBYTE *
- * This procedure reads a byte from the ispSTREAM. *
- *************************************************************/
- unsigned char GetByte()
- {
- return (*fp++);
- }
-
-
- /*************************************************************
- * *
- * SCLOCK *
- * This procedure apply a clock to TCK. *
- *************************************************************/
- void sclock(void)
- {
- isp_setpin(out_SCLK,HIGH);
- isp_setpin(out_SCLK,LOW);
- }
-
- /*************************************************************
- * *
- * SHIFT/EXECUTE *
- * *
- *************************************************************/
- void execute()
- {
- isp_setpin(out_MODE, HIGH);
- isp_setpin(out_SDI, HIGH);
- sclock();
- isp_setpin(out_SDI, LOW);
- isp_setpin(out_MODE, LOW);
- }
-
-
- /*************************************************************
- * *
- * MOVE TO ID STATE *
- * *
- *************************************************************/
-
- void move_to_id_state()
- {
- isp_setpin(out_MODE, HIGH);
- isp_setpin(out_SDI, LOW); /*extra delay for device to settle*/
- sclock();
- isp_setpin(out_MODE, LOW);
- }
-
-
- /*************************************************************
- * *
- * READ_ISPSTREAM_HEADER *
- * Extract the header from the ispSTREAM file. *
- * Return *
- * ChainLength--------number of ispLSI devices in the *
- * given daisy chain. *
- * ErasePulse---------pulse width in mS for device *
- * bulk erase. *
- * ProgramPulse-------pulse width in mS for device *
- * row by row programming. *
- * RowLength----------the number of rows of data +UES *
- * DataSize-----------the size of each row of data *
- * IDStreamLength-----the bit length of the ID stream. *
- *************************************************************/
- void ReadispSTREAMHeader(short int *ChainLength, short int *ErasePulse,
- short int *ProgramPulse, short int *RowLength,
- unsigned short int *DataSize,
- unsigned short int *IDStreamLength)
- {
-
- *ChainLength = GetByte();
- *ErasePulse = GetByte() * 0x100;
- *ErasePulse += GetByte();
- *ProgramPulse = GetByte();
- *RowLength = GetByte() * 0x100;
- *RowLength += GetByte();
- *DataSize = GetByte() * 0x100;
- *DataSize += GetByte();
- *IDStreamLength = GetByte() * 0x100;
- *IDStreamLength += GetByte();
- /*End of the header of the ispSTREAM file.*/
-
- }
-
- /*****************************************************************
- * *
- * READ_ISPSTREAM_DATA *
- * Extract the data from the ispSTREAM file. *
- * DataSize-----------The number of data bits to be fetched. *
- * SS-----------------Super SLIM ispSTREAM file if true. *
- * Return *
- * InData-------------The data stream from ispSTREAM file *
- ******************************************************************/
- void ReadispSTREAMData(unsigned short int DataSize, unsigned char *InData,
- char SS)
- {
- unsigned short int index;
- short int i,j;
- unsigned char xch;
- static short int FFcount=0; /*5.1*/
-
- j=0;
- xch=0;
- for (index=0; index<DataSize; index++)
- {--bit;
- if (bit<0)
- {if (FFcount<=0) /*5B.001 Read a new byte if 0xFF chain exhausted*/
- { curch = GetByte();
- if ((SS)&&(curch==0xFF)) /*5B.001 Super SLIM ispSTREAM file support*/
- FFcount = GetByte(); /*5B.001 The number of 0xFF bytes*/
- }
- else FFcount--; /*5B.001 Use up the 0xFF chain first*/
- bit=7;
- }
- if ((curch >> bit) & 0x01) xch |= 0x80 >> index%8;
- if (index%8==7) {InData[j++] = xch; xch=0;}
- }
- InData[j] = xch; /*save the last byte of the current row*/
- }
-
- /*************************************************************
- * *
- * ispInstruction *
- * Send the instruction streams to the devices. *
- * ChipCount-------The number of devices in the chain. *
- * Command---------The command to be sent to all devices. *
- *************************************************************/
- void ispInstruction(short int ChipCount, unsigned char Command)
- {
- char Instruction = 5; /*All Lattice devices have 5 bit commands*/
- short int index;
- short int i;
- for (index = 0; index < ChipCount; index++) {
- for (i=0; i<Instruction; i++)
- {isp_setpin(out_SDI, (Command >> i)&0x01);
- sclock(); /*clock the data into the command registers */
- }
- }
- }
-
- /*************************************************************
- * *
- * ispAddress *
- * Send the Address streams to the devices. *
- * ChipCount-------The number of devices in the chain. *
- * Address---------The full address for the devices. *
- *************************************************************/
- void ispAddress(short int ChipCount, short int RowLength)
- {
- short int index;
- short int i;
- unsigned short int condition; /*0x1000 HD devices*/
- /*0x2000 HD devices with UES*/
- /*0x3000 Single row per address HD devices*/
- /*0x4000 Single row per address HD devices with UES*/
-
- condition = RowLength & 0xF000;
- RowLength = RowLength & 0x0FFF; /*Mask out the condition bits*/
- if ((condition==0x2000)||(condition==0x4000))
- RowLength = (RowLength-1)/2; /*Exclude the UES row from address*/
- else if ((condition==0x1000)||(condition==0x3000))
- RowLength = RowLength/2; /*High Low Order addressing*/
-
- for (index = 0; index < ChipCount; index++) {
- for (i=1; i<RowLength; i++)
- sclock(); /*clock zeros into the address registers */
- isp_setpin(out_SDI,HIGH);
- sclock(); /*clock a one into the address registers*/
- isp_setpin(out_SDI,LOW);
- }
- execute(); /*step to shift state*/
- }
-
- /**********************************************************************
- * *
- * ispData *
- * Send the data stream to devices. *
- * InData-----------The data stream to be sent to devices. *
- * DataSize---------The length of the data stream. *
- ***********************************************************************/
- void ispData(unsigned char *InData, unsigned short int DataSize)
- {
- unsigned short int index;
- short int i,j;
- unsigned char xch;
-
- j=0;
- for (index = 0; index <DataSize; index++) {
- if (index%8==0) xch = InData[j++];
- isp_setpin(out_SDI, (((xch << index%8) & 0x80) ? 0x01 : 0x00));
- sclock(); /*clock data into the data shift registers */
- }
- execute(); /*step to shift state*/
- }
-
- /**********************************************************************
- * *
- * ispRead *
- * Read the data stream from devices and verify. *
- * DataSize---------The length of the data stream. *
- * OutData----------The data stream to be compare with those read *
- * from devices. *
- ***********************************************************************/
- char ispRead(unsigned short int DataSize, unsigned char *OutData)
- {
- unsigned short int index,error;
- short int i,j;
- unsigned char xch,cur_bit;
-
- j=0;
- error=0;
- xch=0;
- for (index = 0; index <DataSize; index++) {
- if (index%8==0) xch = OutData[j++];
- cur_bit=isp_SDO();
- if (cur_bit != (((xch << index%8) & 0x80) ? 0x01 : 0x00)) error++;
- sclock(); /*clock data out from the data shift registers */
- }
- execute(); /*step to shift state*/
- if (error > 0) return 1; /*Flag failure occur*/
- else return (0);
- }
-
- /*************************************************************
- * *
- * ISPSTREAM_PUMP *
- * *
- *************************************************************/
-
- short int ispstream_pump(short int operation, short int *end)
- {
- short int row;
- short int HDDevices,HighLow; /*device types identifiers*/
- char SS; /*ispSTREAM file types identifier*/
- unsigned char Command,UES,FileType;
- short int last_row,
- erase_pulse,
- program_pulse,
- devices_in_chain;
- unsigned short int maxi_data,
- data_length,
- id_length;
- short int rcode;
- short int DeviceType,EndRow;
- unsigned char *buf;
-
- row =0;
- bit = 0;
- /*Start reading the header of the ispSTREAM file*/
- fp = ispstream;
- FileType = GetByte();
- if (FileType == 0x00) {SS=false;} /*Check for correct file type*/
- else if (FileType == 0x02 ) {SS=true;} /*Super SLIM ispSTREAM file found*/
- else {
- return FILE_NOT_JEDEC;
- }
- ReadispSTREAMHeader(&devices_in_chain, &erase_pulse, &program_pulse,
- &last_row, &maxi_data, &id_length);
-
- rcode = OK; /*Success by default.*/
- DeviceType = last_row & 0xF000; /*Device types code*/
- EndRow = last_row & 0x0FFF; /*Actual address length*/
- if (DeviceType >= 0x1000)
- HDDevices = true; /*ispLSI devices found*/
- else HDDevices = false; /*ispGAL or ispGDS found*/
- if ((DeviceType == 0x1000) || (DeviceType == 0x2000))
- HighLow = true; /*Devices need High/Low addressing detected*/
- else HighLow = false;
- if ((DeviceType==0x2000)||(DeviceType==0x4000))
- UES=true; /*UES programming required*/
- else UES=false;
- if ((operation==verify)||(operation==verify_ues)) /*verify only*/
- {erase_pulse=0; /*void the erase instruction*/
- program_pulse=0; /*void the program instruction*/
- }
- if ((operation==verify_ues)&&(!UES)) /*The ispSTREAM has no UES*/
- return FILE_NOT_JEDEC;
-
- /*Allocate memory to store one row of data from the ispSTREAM file.*/
- buf = buffer;
- isp_pins = NUL; /* intialize to drive all port pins LOW*/
- isp_setpin(out_ISP, LOW);/* drive ispEN pin low to enable the
- ISP controlling pins:
- SCLK,MODE,SDI and SDO.*/
- move_to_id_state(); /*Initialise the devices*/
- execute(); /*Synchronize the devices*/
- move_to_id_state(); /*Load the IDs*/
- ReadispSTREAMData(id_length,buf,SS); /*fetch ID stream from ispSTREAM*/
- rcode = ispRead(id_length,buf); /*verify the ID stream*/
- if (rcode != OK)
- return UNKNOWN_CHIP;
- if (erase_pulse > 0) /*erase the devices*/
- {
- if (HDDevices) Command = ERASE_ALL;
- else Command = ERASE;
- ispInstruction(devices_in_chain,Command);
- execute(); /*step to execute state*/
- sclock(); /*start the erase timing*/
- pulse_width(erase_pulse); /*erase pulse*/
- isp_setpin(out_MODE, HIGH);
- isp_setpin(out_SDI,HIGH);
- pulse_width(1); /*super voltage discharge*/
- sclock();
- isp_setpin(out_SDI,LOW);
- isp_setpin(out_MODE,LOW); /*devices in shift state*/
- }
- if (operation==verify_ues) /*verify ues only*/
- {for (row=1; row<EndRow; row++) /*skip array data */
- {
- if ((HDDevices)&&(!HighLow)&&(row%2==0))/*single address per row HD devices*/
- {} /*devices have no Low Order rows*/
- else
- ReadispSTREAMData(maxi_data,buf,SS); /*fetch and trash ispSTREAM*/
- }
- }
- else row =1;
-
-
- /*start processing the rows in the ispSTREAM file*/
-
- for (; row <= EndRow; row++) {
- *end = row; /* The row number where process ended.*/
- if ((HDDevices)&&(!HighLow)&&(row%2==0))/*single address per row HD devices*/
- {} /*devices have no Low Order rows*/
- else {
- if ((HDDevices)&&(row%2==1)) /* Addressing for ispLSI devices*/
- {
- ispInstruction(devices_in_chain,SHIFT_ADDRESS);
- execute(); /*step to execute state*/
- if (row==1) /* Full addressing once*/
- ispAddress(devices_in_chain,last_row);
- else {sclock(); execute();} /*shift to next address*/
- }
- if ((!HDDevices)&&(row==45)) /*fetch ispGAL22v10 ARCH row*/
- data_length = 20*devices_in_chain;
- else data_length = maxi_data;
- ReadispSTREAMData(data_length,buf,SS); /*fetch data stream from ispSTREAM*/
- if ((!HDDevices)&&(row==45)) /*ispGAL22v10 ARCH row*/
- Command = ARCH_SHIFT;
- else Command = SHIFT_DATA;
- ispInstruction(devices_in_chain,Command);
- execute(); /*step to execute state*/
- ispData(buf,data_length); /*send data into devices*/
- if (program_pulse > 0) /*program and verify*/
- {
- if ((HighLow)&&(row%2==0)) /*Low Order rows*/
- Command = PROGRAM_LOW;
- else Command = PROGRAM_HIGH;
- if ((UES)&&(row==EndRow)) Command = PROGRAM_UES;
- ispInstruction(devices_in_chain,Command);
- execute(); /*step to execute state*/
- sclock(); /*start program timing*/
- pulse_width(program_pulse);
- execute(); /*step to shift state*/
- }
- if ((HighLow)&&(row%2==0)) /*Low Order rows*/
- Command = VERIFY_LOW_PROG;
- else Command = VERIFY_HIGH_PROG;
- if ((UES)&&(row==EndRow)) Command = VERIFY_UES;
- ispInstruction(devices_in_chain,Command);
- execute(); /*step to execute state*/
- sclock(); /*start verify timing*/
- pulse_width(1); /*30uS min. verify time*/
- execute(); /*step to shift state*/
- if ((!HDDevices)&&(row==45)) /*ispGAL22v10 ARCH row*/
- Command = ARCH_SHIFT;
- else Command = SHIFT_DATA;
- ispInstruction(devices_in_chain,Command);
- execute(); /*step to execute state*/
- rcode = ispRead(data_length,buf); /*verify the data stream*/
- if (rcode != OK) break;
- }
- }
- move_to_id_state(); /*activate ispGAL and ispGDS*/
- isp_setpin(out_ISP,HIGH); /*activate ispLSI devices*/
- if (rcode==OK) return (OK);
- else return VALIDATION_ERROR;
-
- }
-
- /*************************************************************
- * *
- * error_handler *
- * *
- * rcode - error code *
- * *
- * *
- * This procedure return the address of the message string *
- * for the corresponding error code. *
- * *
- *************************************************************/
-
- void error_handler(short int rcode, char *message)
- {
-
- char *error_message[] = {{"PASS"},{""},{""},{"PC Hardware Problem"},{""},
- {""},{""},
- {"No Device Found/Open Download Cable/Open Daisy Chain"},
- {"Can't Find the File"},{""},{"Not Enough PC Memory"},
- {"Verification Fail"},{""},{""},
- {""},
- {"The Chip Count in the Chain and the File Do Not Match"},
- {"Unknown Device Found"},{"Wrong File Type"},{"File Error"},
- {""}};
-
- strcpy(message, error_message[-rcode]);
- }
-
-
-
- /*************************************************************
- * *
- * MAIN *
- * *
- *************************************************************/
-
- short int main(int argc, char *argv[])
- {
- short int rcode = OK,
- end = 0;
- char str[300];
- short int operation=prog_verify; /*3.05 Default to Program and Verify*/
-
- printf("\n Lattice Semiconductor Corp.\n");
- printf("\n ispCODE V5B.002 Copyright 1996,1997.\n");
- printf("\n SLIM ispSTREAM Driver for ispLSI Devices\n");
- printf("\n For Simple Daisy Chain of The Same Device Type On LSC ISP Controller\n\n");
-
- if ((argc < 1) || (argc > 2)) {
- printf("\nUsage: sturbo [operation]\n");
- printf("Example: sturbo pv\n");
- printf("\n");
- printf("operation \"pv\" = program and verify\n");
- printf(" \"v\" = Verify only\n");
- printf(" \"uv\" = Verify UES only\n");
- printf(" Default to pv if operation is not entered.\n");
- exit(1);
- }
-
- /*3.02 set the initial condition of the parallel port*/
- /* All the port_pins defined on lattice.h will be controlled by
- ispstream_pump(). The rest can be initialized here either to
- HIGH or LOW and won't be altered by isptream_pump*/
-
- if (rcode == OK){ /*start programming and verification*/
-
- if(!strcmp(strlwr(argv[1]),"uv")){ /*3.05 What to do? uv=ues verify only*/
- operation=verify_ues; /*for verify ues only =1*/
- printf("\nStart Verify UES of ispLSI devices.......\n");}
- else if(!strcmp(strlwr(argv[1]),"v")){ /*v = verify only*/
- operation=verify;
- printf("\nStart Verify.......\n");}
- else { /*pv = program and verify: Default*/
- operation=prog_verify;
- printf("\nStart Program and Verify.......\n");
- }
-
- rcode = ispstream_pump(operation, &end); /*3.05 add operation switch*/
- }
- if (rcode != OK) {
- error_handler(rcode, str);
- printf("\nFailed At Row %d in Program and Verify Due To %s\n", end, str);
- printf("\n");
- printf("+-------+\n");
- printf("| FAIL! |\n");
- printf("+-------+\n");
- return (-rcode);
- } else {
- printf("\n");
- printf("+=======+\n");
- printf("| PASS! |\n");
- printf("+=======+\n");
- }
-
- return(0);
- }